package com.junchenrobot.mes.core;


import com.junchenrobot.mes.client.KCClient;
import com.junchenrobot.mes.config.AsyncPool;
import com.junchenrobot.mes.dao.*;
import com.junchenrobot.mes.domain.*;
import com.junchenrobot.mes.dto.PoolTask;
import com.junchenrobot.mes.dto.param.TaskParam;
import com.junchenrobot.mes.dto.response.VehicleStatusDto;
import com.junchenrobot.mes.dto.response.VehicleStatusListDto;
import com.junchenrobot.mes.enums.DeviceStatusEnum;
import com.junchenrobot.mes.enums.ExecuteStateEnum;
import com.junchenrobot.mes.enums.PoolStateEnum;
import com.junchenrobot.mes.listener.source.WinderTaskRedisRepository;
import com.junchenrobot.mes.util.TaskCodeUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Component
public class TaskScheduled {

    private final TaskStored taskStored;
    private final WinderTimeDao winderTimeDao;
    private final KCClient kcClient;

    private final WinderDao winderDao;

    private final WinderTaskDao winderTaskDao;

    private final AgvWorkDao agvWorkDao;

    private final DeviceDao deviceDao;

    private final WinderTaskSpareDao winderTaskSpareDao;

    private final WinderTaskRunDao winderTaskRunDao;

    @Autowired
    public TaskScheduled(TaskStored taskStored, KCClient kcClient, WinderDao winderDao, WinderTaskDao winderTaskDao,
                         AgvWorkDao agvWorkDao, WinderTimeDao winderTimeDao, DeviceDao deviceDao, WinderTaskSpareDao winderTaskSpareDao, WinderTaskRunDao winderTaskRunDao) {
        this.taskStored = taskStored;
        this.winderTimeDao = winderTimeDao;
        this.kcClient = kcClient;
        this.winderDao = winderDao;
        this.winderTaskDao = winderTaskDao;
        this.agvWorkDao = agvWorkDao;
        this.deviceDao = deviceDao;
        this.winderTaskSpareDao = winderTaskSpareDao;
        this.winderTaskRunDao = winderTaskRunDao;
    }

    public void createWinderTask(List<AgvWork> workList) {
        List<WinderTaskSpare> collect = workList.stream()
                .map(v -> WinderTaskSpare.builder()
                        .taskCode(TaskCodeUtil.createTaskCode())
                        .taskDeviceId(1L)
                        .taskType(1)
                        .taskWinderLine(v.getLine())
                        .taskWinderId(v.getId())
                        .taskWinderLsh(v.getLsh())
                        .taskWinderSpinningCode(v.getSpinNo())
                        .taskExecuteStatus(-1)
                        .taskWarnTime(v.getTime())
                        .build())
                .collect(Collectors.toList());
        // 取出索引
        List<Long> indexList = taskStored.listTaskIndex();

        //获取正在运行的所有任务
        List<WinderTaskRun> winderTaskRuns = winderTaskRunDao.listUnFinishedTask();
        //获取备选任务列表
        List<WinderTaskSpare> winderTaskSpares = winderTaskSpareDao.listUnFinishedTask();
        //获取当前时间
        LocalDateTime time = LocalDateTime.now().minusSeconds(20);

        //去重操作
        List<WinderTaskSpare> winderTaskSpareList = collect.stream()
                .filter(Objects::nonNull)
                //去除正在运行的任务
                .filter(a -> winderTaskRuns.stream()
                        .filter(Objects::nonNull)
                        .noneMatch(id -> Objects.equals(a.getTaskWinderId(), id.getTaskWinderId())))
//                //去除备用列表里存在的任务
//                .filter(b -> winderTaskSpares.stream()
//                        .filter(Objects::nonNull)
//                        .noneMatch(id -> Objects.equals(b.getTaskWinderId(), id.getTaskWinderId())))
                //去除比超过(现在时间减20秒后)的时间的任务
                .filter(b -> b.getTaskWarnTime().isBefore(time))
                .collect(Collectors.toList());
//        List<WinderTask> collect1 = collect.stream()
//                .filter(Objects::nonNull)
//                .filter(a -> indexList.stream()
//                        .filter(Objects::nonNull)
//                        .noneMatch(id -> Objects.equals(a.getTaskWinderId(), id)))
//                .collect(Collectors.toList());
        log.info("去重后的任务数量:{}", winderTaskSpareList.size());
        if (winderTaskSpareList.size() > 0) {

            for (WinderTaskSpare winderTask : winderTaskSpareList) {
                log.info(":去重后:{},{},{}", winderTask.getTaskWinderId(), winderTask.getTaskWinderLine(), winderTask.getTaskWinderSpinningCode());
            }

            //log.info("强转后的数量:{]");
            taskStored.addWinderTask(winderTaskSpareList);
            //log.info("添加到数据库");
            //log.info("TaskPoolSize: {}", taskStored.taskSize());
            //log.info("TaskIndexSize: {}", taskStored.size());
        }
    }

    /**
     * 获取最优任务
     *
     * @return {@link WinderTask}
     */
    public WinderTaskSpare getOptimalTask() {
        log.info("准备");
        if (taskStored.taskSize() != 0) {
            // 取出一个任务
            log.info("获取任务");
            final WinderTaskSpare task = taskStored.getFirst();
            log.info("获取的任务为:{}", task);
            // 产线
            //Integer taskWinderLine = task.getTaskWinderLine();
            //// 纺丝号
            //Integer taskWinderSpinningCode = task.getTaskWinderSpinningCode();
            // 查询作业
            //AgvWork agvWork = agvWorkDao.getAgvWork(taskWinderLine, taskWinderSpinningCode);
            AgvWork agvWork = agvWorkDao.getAgvWork(task.getTaskWinderId());
            log.info("agvWork:{}", agvWork);
            // avg数据库里任务还存在
            if (!Objects.isNull(agvWork) && agvWork.getStatus() == 1) {
                log.info("****");
                return task;
            }
        }
        return null;
    }

    @Autowired
    WinderTaskRedisRepository winderTaskRedisRepository;


    /**
     * 分派左杆任务
     *
     * @param task 任务
     */
    public void dispatchTask(WinderTaskSpare task, Device device, Integer devicePole) {
        log.info("-6-");
        // 取出信息
        //线号
        Integer taskWinderLine = task.getTaskWinderLine();
        //卷绕机号
        Integer taskWinderSpinningCode = task.getTaskWinderSpinningCode();
        // 查询卷绕机
        log.info("-7-");
        Winder winder = winderDao.getWinder(taskWinderLine, taskWinderSpinningCode);
        if (devicePole == 1) {
            //拿到任务目标点位
            task.setTaskLocation(winder.getWinderLeftPosition());
        } else {
            //拿到任务目标点位
            task.setTaskLocation(winder.getWinderRightPosition());
        }

        //删除备用列表里上面获取的任务
        winderTaskSpareDao.deleteWinderTask(task);

        task.setTaskPoleCode(devicePole);
        task.setTaskDeviceId(device.getId());
        task.setTaskDeviceName(device.getDeviceName());
        //下发取料任务
        deliverTheFetchTask(task);
    }

    /**
     * 设置小车状态
     */
    public void getVehicleStatusList() {
        log.info("-2-");
        VehicleStatusListDto vehicleStatusListDto = kcClient.vehicleStatus();
        log.info("-3-");
        //获取到所有小车的状态
        List<VehicleStatusDto> vehicleStatus = vehicleStatusListDto.getVehicleStatus();
        log.info("-4-{}", vehicleStatus.size());
        for (VehicleStatusDto vehicleStatusDto : vehicleStatus) {
            String status = vehicleStatusDto.getStatus();

            String vehicleNo = vehicleStatusDto.getVehicleNo();
            String battery = String.format("%.2f", vehicleStatusDto.getBattery());
            deviceDao.updateDeviceBattery(vehicleNo, battery);

            log.info("=1=status:{}", status);
            Integer deviceStatus = deviceDao.getDevice(vehicleStatusDto.getVehicleNo()).getDeviceStatus();
            log.info("=2=deviceStatus:{}", deviceStatus);
            if (deviceStatus.equals(99)) {
                log.info("禁用小车!");
            } else {
                switch (status) {
                    //设置为充电
                    case "charging":
                        if (winderTaskSpareDao.selectCount() >= 6L && vehicleStatusDto.getBattery() >= new Double(0.71)) {
                            deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.IDLE.getIndex());
                            log.info("备用任务>=6个并且电量大于71%,设置空闲");
                        } else {
                            deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.CHARGING.getIndex());
                            log.info("设置为充电");
                        }
                        Integer deviceStatus1 = deviceDao.getDevice("1").getDeviceStatus();
                        Integer deviceStatus2 = deviceDao.getDevice("2").getDeviceStatus();
                        Integer deviceStatus3 = deviceDao.getDevice("3").getDeviceStatus();
                        String deviceBattery = deviceDao.getDevice("1").getDeviceBattery();
                        double deviceBattery1 = Double.parseDouble(deviceBattery);
                        String deviceBattery2 = deviceDao.getDevice("2").getDeviceBattery();
                        double deviceBattery3 = Double.parseDouble(deviceBattery2);
                        if (deviceStatus1.equals(DeviceStatusEnum.CHARGING.getIndex()) && (deviceStatus2.equals(DeviceStatusEnum.CHARGING.getIndex()) || deviceStatus3.equals(DeviceStatusEnum.CHARGING.getIndex())) && deviceBattery1 > 0.75) {
                            deviceDao.updateDevice("1", DeviceStatusEnum.IDLE.getIndex());
                            log.info("1,3车在充电或者1,2车在充电并且1车电量大于75%,将1车改为空闲");
                        } else if (deviceStatus2.equals(DeviceStatusEnum.CHARGING.getIndex()) && deviceStatus3.equals(DeviceStatusEnum.CHARGING.getIndex()) && deviceBattery3 > 0.75) {
                            deviceDao.updateDevice("2", DeviceStatusEnum.IDLE.getIndex());
                            log.info("2,3车在充电并且2车电量大于75%,将2车改为空闲");
                        }
                        break;
                    //设置为空闲
                    case "idle":
                        deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.IDLE.getIndex());
                        log.info("设置为空闲");
                        break;
                    //设置为任务进行中
                    case "running":
                        deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.RUNNING.getIndex());
                        log.info("设置为任务进行中");
                        break;
                    //设置为离线
                    case "offline":
                        deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.OFFLINE.getIndex());
                        log.info("设置为离线");
                        break;
                    //设置为无效
                    case "invalid":
                        deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.INVALID.getIndex());
                        log.info("设置为无效");
                        break;
                    //设置为车辆任务被放弃
                    case "aborted":
                        deviceDao.updateDevice(vehicleNo, DeviceStatusEnum.ABORTED.getIndex());
                        log.info("设置为车辆任务被放弃");
                        break;
                }
            }
        }

        log.info("-5-");
    }

    /**
     * 获取设备状态并分派任务
     *
     * @return
     */
    public void deviceTask(String deviceName) {
        //获取设备信息
        Device device = deviceDao.getDevice(deviceName);
        //拿到设备左杆
        Integer deviceLeftPole = device.getDeviceLeftPole();
        //拿到设备右杆
        Integer deviceRightPole = device.getDeviceRightPole();

        Integer devicePole = deviceLeftPole * 10 + deviceRightPole;

        //拿到该设备的设备状态
        Integer deviceStatus = device.getDeviceStatus();
        //判断设备为空闲状态
        if (deviceStatus == DeviceStatusEnum.IDLE.getIndex()) {
            log.info("+++1++");
            switch (devicePole) {
                case 0:
                case 9:
                    //拿到最优任务
                    WinderTaskSpare winderTask = getOptimalTask();
                    if (winderTask == null) {
                        log.info("++");
                        return;
                    }
                    log.info("*1*");
                    Integer devicePole1 = 1;
                    //修改设备信息
                    log.info("*2*");
                    deviceDao.updateDevicePoleStatus(device.getDeviceName(), devicePole1, PoolStateEnum.PICKING_TASK.getState());
                    //分配任务
                    dispatchTask(winderTask, device, devicePole1);
                    break;
                case 30:
                case 39:
                    PointLine pointLine = pointLines(deviceName);
                    Integer taskPoleCode = 1;
                    log.info("分配左杆任务:设备名称:{},{}杆,当前线号:{},当前目标点位:{}", deviceName, taskPoleCode, pointLine.getTaskWinderLine(), pointLine.getCurrentPoint());
                    //获取最优任务
                    WinderTaskSpare winderTaskSpare = getAndSendRightWinderTask(pointLine.getTaskWinderLine(), pointLine.getCurrentPoint());
                    if (winderTaskSpare == null) {
                        deviceDao.updateDevicePoleStatus(deviceName, taskPoleCode, PoolStateEnum.IDLE.getState());
                    } else {
                        //写入参数
                        WinderTaskSpare taskSpare = writeTaskParameter(winderTaskSpare, deviceName, taskPoleCode);
                        //修改设备信息
                        deviceDao.updateDevicePoleStatus(device.getDeviceName(), taskPoleCode, PoolStateEnum.PICKING_TASK.getState());
                        //下发取料任务
                        deliverTheFetchTask(taskSpare);
                    }
                    break;
                case 40:
                case 43:
                    pointLine = pointLines(deviceName);
                    taskPoleCode = 2;
                    log.info("分配右杆任务:设备名称:{},{}杆,当前线号:{},当前目标点位:{}", deviceName, taskPoleCode, pointLine.getTaskWinderLine(), pointLine.getCurrentPoint());
                    //获取最优任务
                    WinderTaskSpare taskSpare = getAndSendRightWinderTask(pointLine.getTaskWinderLine(), pointLine.getCurrentPoint());
                    if (taskSpare == null) {
                        deviceDao.updateDevicePoleStatus(deviceName, taskPoleCode, PoolStateEnum.NO_PICKUP_TASK.getState());
                    } else {
                        //写入参数
                        WinderTaskSpare winderTaskSpare1 = writeTaskParameter(taskSpare, deviceName, taskPoleCode);
                        //修改设备信息
                        deviceDao.updateDevicePoleStatus(device.getDeviceName(), taskPoleCode, PoolStateEnum.PICKING_TASK.getState());
                        //下发取料任务
                        deliverTheFetchTask(winderTaskSpare1);
                    }
                    break;
                case 41:
                    // 查询所有放料任务
                    List<WinderTask> winderTaskList = winderTaskDao.listTaskCondition(deviceName,
                            ExecuteStateEnum.TASK_WAITING.getState(), 2);
                    log.info("有{}个放料任务", winderTaskList.size());
                    for (WinderTask task : winderTaskList) {
                        WinderTaskSpare winderTaskSpare1 = WinderTaskSpare.builder().build();
                        BeanUtils.copyProperties(task, winderTaskSpare1);
                        // 下发放料任务
                        issueTheMaterialTask(winderTaskSpare1, winderTaskSpare1.getTaskPoleCode());
                        deviceDao.updateDevicePoleStatus(winderTaskSpare1.getTaskDeviceName(), winderTaskSpare1.getTaskPoleCode(), PoolStateEnum.FEEDING_FAILURE.getState());
                    }
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 44:
                    // 查询所有放料任务
                    winderTaskList = winderTaskDao.listTaskCondition(deviceName,
                            ExecuteStateEnum.TASK_WAITING.getState(), 2);
                    log.info("有{}个放料任务", winderTaskList.size());
                    WinderTask winderTask1 = winderTaskList.get(0);
                    WinderTaskSpare winderTaskSpare1 = WinderTaskSpare.builder().build();
                    BeanUtils.copyProperties(winderTask1, winderTaskSpare1);
                    // 下发放料任务
                    issueTheMaterialTask(winderTaskSpare1, 3);
                    deviceDao.updateDevicePoleStatus(winderTaskSpare1.getTaskDeviceName(), 1, PoolStateEnum.FEEDING_FAILURE.getState());
                    deviceDao.updateDevicePoleStatus(winderTaskSpare1.getTaskDeviceName(), 2, PoolStateEnum.FEEDING_FAILURE.getState());
                    break;
                case 4:
                case 64:
                case 46:
                case 94:
                case 49:
                    // 查询所有放料任务
                    winderTaskList = winderTaskDao.listTaskCondition(deviceName,
                            ExecuteStateEnum.TASK_WAITING.getState(), 2);
                    log.info("有{}个放料任务", winderTaskList.size());
                    for (WinderTask task : winderTaskList) {
                        winderTaskSpare1 = WinderTaskSpare.builder().build();
                        BeanUtils.copyProperties(task, winderTaskSpare1);
                        // 下发放料任务
                        issueTheMaterialTask(winderTaskSpare1, winderTaskSpare1.getTaskPoleCode());
                        deviceDao.updateDevicePoleStatus(winderTaskSpare1.getTaskDeviceName(), winderTaskSpare1.getTaskPoleCode(), PoolStateEnum.FEEDING_FAILURE.getState());
                    }
                    break;
                case 61:
                case 60:
                    log.info("左杆放料删除");
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 66:
                    log.info("左右杆放料删除");
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 67:
                    log.info("左杆放料删除,右杆放料完成");
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 70:
                    log.info("左杆放料完成!");
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    break;
                case 76:
                    log.info("左杆放料完成!右杆放料删除");
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 77:
                    log.info("左右杆放料完成");
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 90:
                    //拿到最优任务
                    winderTask = getOptimalTask();
                    if (winderTask == null) {
                        return;
                    }
                    //分配任务
                    devicePole1 = 2;
                    //修改设备信息
                    deviceDao.updateDevicePoleStatus(device.getDeviceName(), devicePole1, PoolStateEnum.PICKING_TASK.getState());

                    dispatchTask(winderTask, device, devicePole1);
                    break;
                case 7:
                case 6:
                case 1:
                case 91:
                case 96:
                case 97:
                    deviceDao.updateDevicePoleStatus(deviceName, 2, PoolStateEnum.IDLE.getState());
                    break;
                case 3:
                case 63:
                case 93:
                    pointLine = pointLines(deviceName);
                    taskPoleCode = 2;
                    log.info("分配右杆任务:设备名称:{},{}杆,当前线号:{},当前目标点位:{}", deviceName, taskPoleCode, pointLine.getTaskWinderLine(), pointLine.getCurrentPoint());
                    //获取最优任务
                    taskSpare = getAndSendRightWinderTask(pointLine.getTaskWinderLine(), pointLine.getCurrentPoint());
                    if (taskSpare == null) {
                        deviceDao.updateDevicePoleStatus(deviceName, taskPoleCode, PoolStateEnum.NO_PICKUP_TASK.getState());
                    } else {
                        //写入参数
                        winderTaskSpare1 = writeTaskParameter(taskSpare, deviceName, taskPoleCode);
                        //修改设备信息
                        deviceDao.updateDevicePoleStatus(device.getDeviceName(), taskPoleCode, PoolStateEnum.PICKING_TASK.getState());
                        //下发取料任务
                        deliverTheFetchTask(winderTaskSpare1);
                    }
                    break;
                case 69:
                case 79:
                    deviceDao.updateDevicePoleStatus(deviceName, 1, PoolStateEnum.IDLE.getState());
                    break;
                default:
                    log.info("没有匹配的俩个杆子状态!");
            }
        }
    }

    /**
     * 生成放料任务
     *
     * @param winderTask
     */
    public void scheduleOutputWinderTask(WinderTask winderTask) {
        // 生成一个放料任务
        if (!Objects.isNull(winderTask)) {

            String taskCode = winderTask.getTaskCode();
            winderTask.setTaskType(2);
            winderTask.setTaskLocation("1");
            winderTask.setId(null);
            winderTask.setTaskCode(TaskCodeUtil.createTaskCode());
            winderTask.setTaskStartTime(null);
            winderTask.setTaskFinishedTime(null);
            winderTask.setTaskExecuteStatus(ExecuteStateEnum.TASK_WAITING.getState());
            winderTaskDao.insertNewTask(winderTask);
            // 更新任务信息 [执行完成]
            WinderTaskRun task1 = winderTaskRunDao.getTaskRun(taskCode);
            winderTaskRunDao.deleteWinderTask(task1);
            winderTaskDao.updateTaskByTaskCode(taskCode, ExecuteStateEnum.TASK_FINISHED.getState());
        }
    }

    /**
     * 获取前一个任务分配下一个的任务
     *
     * @param taskWinderLine         线号
     * @param taskWinderSpinningCode 卷绕机机号
     * @return
     */
    public WinderTaskSpare getAndSendRightWinderTask(Integer taskWinderLine, Integer taskWinderSpinningCode) {
        WinderTaskSpare winderTask = null;
        //添加右杆取料任务
        //根据前车判断
        //读取所有的小车作业
        List<WinderTaskRun> winderTaskRuns = winderTaskRunDao.listUnFinishedTask();
        //读取任务池的所有任务
        List<WinderTaskSpare> winderTaskSpareList = winderTaskSpareDao.listUnFinishedTask();

        if (winderTaskSpareList.size() == 0) {
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
                System.exit(0); //退出程序
            }
            winderTaskSpareList = winderTaskSpareDao.listUnFinishedTask();
        }
        //判断备用任务是否存在
        log.info("备用任务的条数:{}", winderTaskSpareList.size());
        if (winderTaskSpareList.size() > 0) {//如果有备用任务
            //判断任务是否为2号线
            if (taskWinderLine == 2) {
                winderTask = rightStickTask(taskWinderSpinningCode, winderTaskSpareList);
            } else {
                winderTask = rightStickTasks(taskWinderSpinningCode, winderTaskRuns, winderTaskSpareList);
            }
        } //没有备用任务
        return winderTask;
    }

    /**
     * 写入任务的参数
     *
     * @param winderTask 任务
     * @param deviceName 设备名称
     * @param PoleNum    设备杆号
     */
    public WinderTaskSpare writeTaskParameter(WinderTaskSpare winderTask, String deviceName, Integer PoleNum) {
        log.info("--------");
        if (winderTask != null) {
            //执行取料任务
            Device device = deviceDao.getDevice(deviceName);
            Winder winder = winderDao.getWinder(winderTask.getTaskWinderLine(), winderTask.getTaskWinderSpinningCode());
            winderTask.setTaskPoleCode(PoleNum);
            winderTask.setTaskDeviceId(device.getId());
            winderTask.setTaskDeviceName(deviceName);
            if (PoleNum == 1) { // 判断杆状态
                winderTask.setTaskLocation(winder.getWinderLeftPosition());
            } else {// 右杆为满
                winderTask.setTaskLocation(winder.getWinderRightPosition());
            }
        }
        return winderTask;
    }

    /**
     * 获取现在小车的位置
     *
     * @param deviceName 设备名称
     * @return 现在小车的位置
     */
    public PointLine pointLines(String deviceName) {
        PointLine pointLine = new PointLine();
        Integer taskWinderLine;

        VehicleStatusListDto vehicleStatusListDto = kcClient.vehicleStatus();
        //获取到所有小车的状态
        List<VehicleStatusDto> vehicleStatus = vehicleStatusListDto.getVehicleStatus();
        VehicleStatusDto vehicleStatusDto1 = new VehicleStatusDto();
        for (
                VehicleStatusDto vehicleStatusDto : vehicleStatus) {
            if (vehicleStatusDto.getVehicleNo().equals(deviceName)) {
                vehicleStatusDto1 = vehicleStatusDto;
            }
        }
        Integer currentPoint = vehicleStatusDto1.getCurrentPoint();
        if (currentPoint >= 27 && currentPoint <= 29) {
            currentPoint = 3121;
        }
        if (currentPoint >= 24 && currentPoint <= 26) {
            currentPoint = 2121;
        }
        if (currentPoint >= 21 && currentPoint <= 23) {
            currentPoint = 1121;
        }
        if (currentPoint == 6 || currentPoint == 14 || currentPoint == 20) {
            currentPoint = 1011;
        }
        if (currentPoint >= 1011 && currentPoint <= 4122) {
            taskWinderLine = 2;
        } else if (currentPoint >= 5011 && currentPoint <= 8122) {
            taskWinderLine = 1;
        } else {
            currentPoint = 5011;
            taskWinderLine = 1;
        }
        if (taskWinderLine == 1) {
            currentPoint = (currentPoint / 1000 - 5) * 12 + currentPoint % 1000 / 10;
        } else {
            currentPoint = (currentPoint / 1000 - 1) * 12 + currentPoint % 1000 / 10;
        }
        pointLine.setCurrentPoint(currentPoint);
        pointLine.setTaskWinderLine(taskWinderLine);
        return pointLine;
    }


    /**
     * 根据前车任务跟本车位置查询可以接取的任务列表,取出任务
     * 拿到小于本车位置卷绕机机号的小车任务列表
     *
     * @param taskWinderSpinningCode1 左杆任务卷绕机机号
     * @param winderTaskRuns          所有小车任务
     * @param winderTaskSpareList     所有备用任务
     * @return
     */
    public WinderTaskSpare rightStickTasks(Integer taskWinderSpinningCode1, List<WinderTaskRun> winderTaskRuns, List<WinderTaskSpare> winderTaskSpareList) {
        WinderTaskSpare winderTaskSpare = null;
        //拿到1号线大于本车任务卷绕机机号的小车任务
        List<WinderTaskRun> collect = winderTaskRuns.stream()
                .filter(winderTaskRun -> winderTaskRun.getTaskWinderLine().equals(1) && winderTaskRun.getTaskWinderSpinningCode() > taskWinderSpinningCode1)
                .collect(Collectors.toList());
        log.info("获取到1号线其他小车任务数量为:{}", collect.size());
        if (collect.size() == 0) {
            log.info("无一号线其他车任务!");
            List<WinderTaskSpare> winderTaskSpareList1 = getWinderTask(winderTaskSpareList, taskWinderSpinningCode1);
            if (winderTaskSpareList1.size() > 0) {
                for (WinderTaskSpare winderTaskSpare1 : winderTaskSpareList1) {
                    log.info("查询到可以做的任务有:{}", winderTaskSpare1);
                }
                winderTaskSpare = winderTaskSpareList1.get(0);
                winderTaskSpareDao.deleteWinderTask(winderTaskSpare);
            }
            return winderTaskSpare;
        }
        //将小车任务表按卷绕机机号升序排序
        collect.sort((x, y) -> Double.compare(x.getTaskWinderSpinningCode(), y.getTaskWinderSpinningCode()));
        for (WinderTaskRun winderTaskRun : collect) {
            log.info("获取到1号线其他小车的任务为:{}", winderTaskRun);
        }
        //拿到1号线距离自己最近的小车任务
        WinderTaskRun winderTaskRun = collect.get(0);
        log.info("拿到1号线距离自己最近的小车任务为:{}", winderTaskRun);
        //拿到离本车左杆最近的小车卷绕机机号
        Integer taskWinderSpinningCode = winderTaskRun.getTaskWinderSpinningCode();
        //判断俩车是否在1号线同一条机号区
        if ((taskWinderSpinningCode1 - 1) / 12 == (taskWinderSpinningCode - 1) / 12) {
            log.info("在同一区域");
            List<WinderTaskSpare> winderTaskSpareList1 = getWinderTask(winderTaskSpareList, taskWinderSpinningCode1);
                    winderTaskSpare = winderTaskSpareList1.get(0);
            log.info("winderTaskSpare小车右杆接到的任务为:"+winderTaskSpare);
            winderTaskSpareDao.deleteWinderTask(winderTaskSpare);
            return winderTaskSpare;
        }
        //不在1号线同一机号区
        //拿到对应的区域的任务
        Integer i = 49 - (taskWinderSpinningCode - 1) / 12 * 12;
        if (i < 38) {
            List<WinderTaskSpare> winderTaskSpareList1 = getWinderTasks(winderTaskSpareList, i);
            if (winderTaskSpareList1.size() > 0) {
                for (WinderTaskSpare winderTaskSpare1 : winderTaskSpareList1) {
                    log.info("查询到右杆可以做的任务有:{}", winderTaskSpare1);
                }
                winderTaskSpare = winderTaskSpareList1.get(0);
                winderTaskSpareDao.deleteWinderTask(winderTaskSpare);
                log.info("小车右杆接到的任务为:{}", winderTaskSpare);
                return winderTaskSpare;
            }
            //若对应二号线可接任务为0则接本车左杆之后时间最短的任务
            winderTaskSpareList1 = getWinderTask(winderTaskSpareList, taskWinderSpinningCode1);
            if (winderTaskSpareList1.size()>0){
                winderTaskSpare = winderTaskSpareList1.get(0);
                winderTaskSpareDao.deleteWinderTask(winderTaskSpare);
                return winderTaskSpare;
            }

        }
        return winderTaskSpare;
    }

    /**
     * 拿到2号线设备可以分配的最优任务
     *
     * @param taskWinderSpinningCode1 卷绕机机号
     * @param list                    备用任务
     * @return
     */
    public WinderTaskSpare rightStickTask(Integer taskWinderSpinningCode1, List<WinderTaskSpare> list) {
        //查询卷绕机机号大于左杆任务机号的任务列表(按时间排序),取出任务
        WinderTaskSpare task = null;
        //拿到二号线比左杆任务卷绕机机号更大的任务列表
        List<WinderTaskSpare> collect = list.stream()
                .filter(WinderTaskSpare -> WinderTaskSpare.getTaskWinderLine().equals(2) && WinderTaskSpare.getTaskWinderSpinningCode() > taskWinderSpinningCode1)
                .collect(Collectors.toList());
        if (collect.size() > 0) {
            log.info("可以接到的任务数量:{}", collect.size());
            for (WinderTaskSpare winderTaskSpare : collect) {
                log.info("查询到可以做的任务有:{}", winderTaskSpare);
            }
            //分配任务给右杆
            task = collect.get(0);
            winderTaskSpareDao.deleteWinderTask(task);
            log.info("小车接到的任务为:{}", task);
        }
        return task;
    }

    /**
     * 获取左杆任务卷绕机机号之后的任务列表
     *
     * @param list                   所有的备用任务
     * @param taskWinderSpinningCode 当前卷绕机机号
     * @return
     */
    public List<WinderTaskSpare> getWinderTask(List<WinderTaskSpare> list, Integer taskWinderSpinningCode) {
        List<WinderTaskSpare> collect1 = list.stream()
                .filter(WinderTaskSpare -> WinderTaskSpare.getTaskWinderLine().equals(1)
                        && WinderTaskSpare.getTaskWinderSpinningCode() >= taskWinderSpinningCode)
                .collect(Collectors.toList());
        List<WinderTaskSpare> collect2 = list.stream()
                .filter(WinderTaskSpare -> WinderTaskSpare.getTaskWinderLine().equals(2)
                        && WinderTaskSpare.getTaskWinderSpinningCode() >= 1)
                .collect(Collectors.toList());
        collect1.addAll(collect2);
        collect1.sort((x, y) -> Long.compare(x.getTaskWarnTime().toEpochSecond(ZoneOffset.of("+8")), y.getTaskWarnTime().toEpochSecond(ZoneOffset.of("+8"))));
        return collect1;
    }

    /**
     * 获取距离最近小车卷绕机机号的对应二号线本车右杆可做的任务列表
     *
     * @param list 所有的备用任务
     * @param i    当前卷绕机机号
     * @return
     */
    public List<WinderTaskSpare> getWinderTasks(List<WinderTaskSpare> list, Integer i) {
        List<WinderTaskSpare> collect1 = list.stream()
                .filter(WinderTaskSpare -> WinderTaskSpare.getTaskWinderLine().equals(2)
                        && WinderTaskSpare.getTaskWinderSpinningCode() >= i)
                .collect(Collectors.toList());
        return collect1;
    }


    /**
     * 下发取料任务
     *
     * @param first 任务
     */
    public void deliverTheFetchTask(WinderTaskSpare first) {
        CompletableFuture<TaskParam> taskParamCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //任务编号
            String taskCode = first.getTaskCode();
            //任务执行状态
            Integer inTaskExecuteStatus = first.getTaskExecuteStatus();
            log.info("任务类型:{}", inTaskExecuteStatus);
            TaskParam taskParam = new TaskParam();
            //取料
            taskParam.setLocation(first.getTaskLocation());
            taskParam.setTaskType("Pickup");
            taskParam.setPriority(0);
            taskParam.setLoadDirection(first.getTaskPoleCode());
            //强转为小车任务表
            WinderTaskRun winderTaskRun = WinderTaskRun.builder().build();
            BeanUtils.copyProperties(first, winderTaskRun);
            WinderTask winderTask = WinderTask.builder().build();
            BeanUtils.copyProperties(first, winderTask);
            //添加到小车运行任务表
            log.info("要添加进run数据库的是:{},{},{}", winderTaskRun.getTaskWinderId(), winderTaskRun.getTaskWinderLine(), winderTaskRun.getTaskWinderSpinningCode());
            winderTaskRunDao.insertNewTask(winderTaskRun);
            //添加到任务表
            winderTaskDao.insertNewTask(winderTask);
            taskParam.setVehicleNo(first.getTaskDeviceName());
            taskParam.setFinishAction(1);
            taskParam.setTaskCode(taskCode);
            PoolTask poolTask = new PoolTask(taskCode, first.getTaskWinderId());
            AsyncPool.schedule(taskCode, poolTask, 10, TimeUnit.SECONDS);
            log.info("下发定时任务成功");
            return taskParam;
        });
        taskParamCompletableFuture.thenAccept(kcClient::addRegularTask);
        taskParamCompletableFuture.whenComplete((result, e) -> {
            if (e != null) {
                log.error("下发任务异常", e);
            }
        });
    }

    /**
     * 下发放料任务
     *
     * @param first 任务
     */
    public void issueTheMaterialTask(WinderTaskSpare first, Integer taskPoleCode) {
        CompletableFuture<TaskParam> taskParamCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //任务编号
            String taskCode = first.getTaskCode();
            //任务执行状态
            Integer inTaskExecuteStatus = first.getTaskExecuteStatus();
            log.info("任务类型:{}", inTaskExecuteStatus);
            TaskParam taskParam = new TaskParam();
            //放料
            taskParam.setTaskType("Discharge");
            taskParam.setLocation("1");
            taskParam.setPriority(0);
            taskParam.setUnLoadDirection(taskPoleCode);
            taskParam.setVehicleNo(first.getTaskDeviceName());
            taskParam.setFinishAction(0);
            taskParam.setTaskCode(taskCode);
            return taskParam;
        });
        taskParamCompletableFuture.thenAccept(kcClient::addRegularTask);
        taskParamCompletableFuture.whenComplete((result, e) -> {
            if (e != null) {
                log.error("下发任务异常", e);
            }
        });
    }

    public void sendTask(WinderTaskSpare first) {
        CompletableFuture<TaskParam> taskParamCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //任务编号
            String taskCode = first.getTaskCode();
            //任务执行状态
            Integer inTaskExecuteStatus = first.getTaskExecuteStatus();
            log.info("任务类型:{}", inTaskExecuteStatus);
            TaskParam taskParam = new TaskParam();
            //任务类型
            Integer taskType = first.getTaskType();
            if (taskType == 1) {
                //取料
                taskParam.setLocation(first.getTaskLocation());
                taskParam.setTaskType("Pickup");
                taskParam.setPriority(0);
                taskParam.setLoadDirection(first.getTaskPoleCode());
                //强转为小车任务表
                WinderTaskRun winderTaskRun = WinderTaskRun.builder().build();
                BeanUtils.copyProperties(first, winderTaskRun);
                WinderTask winderTask = WinderTask.builder().build();
                BeanUtils.copyProperties(first, winderTask);
                //添加到小车运行任务表
                log.info("要添加进run数据库的是:{},{},{}", winderTaskRun.getTaskWinderId(), winderTaskRun.getTaskWinderLine(), winderTaskRun.getTaskWinderSpinningCode());
                winderTaskRunDao.insertNewTask(winderTaskRun);
                //添加到任务表
                winderTaskDao.insertNewTask(winderTask);
            } else {
                //放料
                taskParam.setTaskType("Discharge");
                taskParam.setLocation("1");
                taskParam.setPriority(0);
                taskParam.setUnLoadDirection(first.getTaskPoleCode());
            }
            taskParam.setVehicleNo(first.getTaskDeviceName());
            taskParam.setFinishAction(0);
            taskParam.setTaskCode(taskCode);
            if (taskType == 1) {
                PoolTask poolTask = new PoolTask(taskCode, first.getTaskWinderId());
                AsyncPool.schedule(taskCode, poolTask, 10, TimeUnit.SECONDS);
                log.info("下发定时任务成功");
            }
            return taskParam;
        });
        taskParamCompletableFuture.thenAccept(kcClient::addRegularTask);
        taskParamCompletableFuture.whenComplete((result, e) -> {
            if (e != null) {
                log.error("下发任务异常", e);
            }
        });
    }
}
